package com.google.code.mochaccino.framework.freemarker;
/*
 * Copyright 2012 Claude Houle claude.houle@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import com.google.code.mochaccino.framework.freemarker.exception.TemplateExceptionHandlerSlf4j;
import freemarker.cache.ConcurrentCacheStorage;
import freemarker.cache.NullCacheStorage;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateExceptionHandler;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;

/** Template Configuration POJO */
public class TemplateConfiguration {

	/** The Caching Strategy */
	private ConcurrentCacheStorage cacheStorage = new NullCacheStorage();

	/** The Date Format in java.text.SimpleDateFormat format. */
	private String dateFormat = null;

	/** The Date Time Format in java.text.SimpleDateFormat */
	private String dateTimeFormat = null;

	/** The User-supplied directives */
	private Map<String,TemplateDirectiveModel> directives = new HashMap<String,TemplateDirectiveModel>();

	/** Encoding */
	private String encoding = null;

	/** Exception Handler */
	private TemplateExceptionHandler exceptionHandler = new TemplateExceptionHandlerSlf4j();
	private boolean                  localizedLookup  = false;
	private String                   numberFormat     = null;
	private ObjectWrapper            objectWrapper    = null;
	private boolean                  stripWhitespace  = false;
	private String                   timeFormat       = null;
	private TimeZone                 timeZone         = null;

	/** Customize Configuration */
	public void customize( Configuration config ) {
		config.setCacheStorage( cacheStorage );
		config.setLocalizedLookup( localizedLookup );
		config.setStrictBeanModels( true );
		config.setStrictSyntaxMode( true );
		config.setWhitespaceStripping( stripWhitespace );

		if ( exceptionHandler != null ) {
			config.setTemplateExceptionHandler( exceptionHandler );
		}
		if ( dateFormat != null ) {
			config.setDateFormat( dateFormat );
		}
		if ( dateTimeFormat != null ) {
			config.setDateTimeFormat( dateTimeFormat );
		}
		if ( timeFormat != null ) {
			config.setTimeFormat( timeFormat );
		}
		if ( timeZone != null ) {
			config.setTimeZone( timeZone );
		}
		if ( encoding != null ) {
			config.setDefaultEncoding( encoding );
		}
		if ( numberFormat != null ) {
			config.setNumberFormat( numberFormat );
		}
		if ( objectWrapper != null ) {
			config.setObjectWrapper( objectWrapper );
		}
		Iterator<Entry<String,TemplateDirectiveModel>> it = directives.entrySet().iterator();
		while ( it.hasNext() ) {
			Entry<String,TemplateDirectiveModel> entry = it.next();
			config.setSharedVariable( entry.getKey(), entry.getValue() );
		}
	}

	/** Customize a Template */
	public void customize( Template tmpl ) {
		if ( exceptionHandler != null ) {
			tmpl.setTemplateExceptionHandler( exceptionHandler );
		}

		if ( dateFormat != null ) {
			tmpl.setDateFormat( dateFormat );
		}
		if ( dateTimeFormat != null ) {
			tmpl.setDateTimeFormat( dateTimeFormat );
		}
		if ( timeFormat != null ) {
			tmpl.setTimeFormat( timeFormat );
		}
		if ( timeZone != null ) {
			tmpl.setTimeZone( timeZone );
		}
		if ( encoding != null ) {
			tmpl.setEncoding( encoding );
		}
		if ( numberFormat != null ) {
			tmpl.setNumberFormat( numberFormat );
		}
		if ( objectWrapper != null ) {
			tmpl.setObjectWrapper( objectWrapper );
		}
	}

	public ConcurrentCacheStorage getCacheStorage() {
		return cacheStorage;
	}

	public void setCacheStorage( ConcurrentCacheStorage cacheStorage ) {
		this.cacheStorage = cacheStorage;
	}

	/** @return the dateformat */
	public String getDateFormat() {
		return dateFormat;
	}

	/** @param format the dateformat to set */
	public void setDateFormat( String format ) {
		this.dateFormat = format;
	}

	/** @return the dateTimeFormat */
	public String getDateTimeFormat() {
		return dateTimeFormat;
	}

	/** @param format the dateTimeFormat to set */
	public void setDateTimeFormat( String format ) {
		this.dateTimeFormat = format;
	}

	/** @return the directives */
	public Map<String,TemplateDirectiveModel> getDirectives() {
		return directives;
	}

	/** @param directiveMap the directives to set */
	public void setDirectives( Map<String,TemplateDirectiveModel> directiveMap ) {
		this.directives = directiveMap;
	}

	/** @return the encoding */
	public String getEncoding() {
		return encoding;
	}

	/** @param enc the encoding to set */
	public void setEncoding( String enc ) {
		this.encoding = enc;
	}

	public TemplateExceptionHandler getExceptionHandler() {
		return exceptionHandler;
	}

	public void setExceptionHandler( TemplateExceptionHandler exceptionHandler ) {
		this.exceptionHandler = exceptionHandler;
	}

	/** @return the numberFormat */
	public String getNumberFormat() {
		return numberFormat;
	}

	/** @param format the numberFormat to set */
	public void setNumberFormat( String format ) {
		this.numberFormat = format;
	}

	/** @return the objectWrapper */
	public ObjectWrapper getObjectWrapper() {
		return objectWrapper;
	}

	/** @param wrapper the objectWrapper to set */
	public void setObjectWrapper( ObjectWrapper wrapper ) {
		this.objectWrapper = wrapper;
	}

	/** @return the timeFormat */
	public String getTimeFormat() {
		return timeFormat;
	}

	/** @param format the timeFormat to set */
	public void setTimeFormat( String format ) {
		this.timeFormat = format;
	}

	/** @return the timeZone */
	public TimeZone getTimeZone() {
		return timeZone;
	}

	/** @param tz the timeZone to set */
	public void setTimeZone( TimeZone tz ) {
		this.timeZone = tz;
	}

	/** @return the localizedLookup */
	public boolean isLocalizedLookup() {
		return localizedLookup;
	}

	/** @param localizedLookup the localizedLookup to set */
	public void setLocalizedLookup( boolean localizedLookup ) {
		this.localizedLookup = localizedLookup;
	}

	/** @return the stripWhitespace */
	public boolean isStripWhitespace() {
		return stripWhitespace;
	}

	/** @param stripWhitespace the stripWhitespace to set */
	public void setStripWhitespace( boolean stripWhitespace ) {
		this.stripWhitespace = stripWhitespace;
	}

	/**
	 * Set Directive
	 * <p/>
	 * <b>Note:</b> Directives cannot be applied directly on a template... You either need to add
	 * it as a configuration directive or add it directly into the Root Model.
	 * </p>
	 */
	public void setDirective( String name, TemplateDirectiveModel directive ) {
		this.directives.put( name, directive );
	}

	/**
	 * Set Time Zone
	 *
	 * @param tzId The TimeZone Id to set
	 */
	public void setTimeZoneId( String tzId ) {
		this.timeZone = TimeZone.getTimeZone( tzId );
	}
}
